package org.budo.dubbo.protocol.http.page;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.budo.dubbo.protocol.http.page.entity.FunctionEntity;
import org.budo.dubbo.protocol.http.page.entity.InterfaceEntity;
import org.budo.dubbo.protocol.http.page.util.InterfaceStructureUtil;
import org.budo.dubbo.protocol.http.util.BudoReflectionUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.spring.io.util.ResourceUtil;

/**
 * @author lmw
 */
public class FunctionPage extends AbstractPage {
    private static final long serialVersionUID = 9189097487835136873L;

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String interfaceName = request.getParameter("interface");
        String functionName = request.getParameter("function");
        this.renderFunctionPage(request, response, interfaceName, functionName);
    }

    private void renderFunctionPage(HttpServletRequest request, HttpServletResponse response, String interfaceNameInUrl, String functionName) throws IOException {
        String matchedInterfaceName = BudoReflectionUtil.getMatchedInterfaceNameCached(interfaceNameInUrl); // 已缓存

        if (null == matchedInterfaceName) {
            List<InterfaceEntity> controllerEntityList = InterfaceStructureUtil.listControllerEntity();
            for (InterfaceEntity controllerMap : controllerEntityList) {
                if (controllerMap.get("simpleName").equals(interfaceNameInUrl)) {
                    matchedInterfaceName = (String) controllerMap.get("typeName");
                }
            }
        }

        if (null == matchedInterfaceName) {
            String errorResponse = "<h1>error:" + " type " + interfaceNameInUrl + " not found" + "</h1>" //
                    + "<a href=\"?from=type-not-found&type=" + interfaceNameInUrl + "\">Back To Index</a>";
            IoUtil.write(new ByteArrayInputStream(errorResponse.getBytes()), response.getOutputStream());
            return;
        }

        Method method = BudoReflectionUtil.getMatchedMethodCached(matchedInterfaceName, functionName);

        if (null == method) {
            String errorResponse = "<h1>error:" + " method " + interfaceNameInUrl + "." + functionName + " not found" + "</h1>" //
                    + "<a href=\"?from=method-not-found&type=" + interfaceNameInUrl + "." + functionName + "\">Back To Index</a>";
            IoUtil.write(new ByteArrayInputStream(errorResponse.getBytes()), response.getOutputStream());
            return;
        }

        Class matchedInterfaceType = ReflectUtil.classForName(matchedInterfaceName);

        FunctionEntity dataMap = InterfaceStructureUtil.interfaceFunctionMap(matchedInterfaceType, method);

        String request_uri_0 = request.getRequestURI().substring(1);
        dataMap.put("request_uri_1", "/" + request_uri_0);

        dataMap.put("request", request);

        String templateInput = ResourceUtil.classPathResourceInputStreamToString("api-doc-template/function.htm");
        this.renderPage(templateInput, dataMap, request, response);
    }
}